using System;
using System.Runtime.InteropServices;
using Framework.Interop;

namespace Framework
{
    ///<summary>
    ///</summary>
    public sealed class ExploreMenuItem : ShellMenuItem
    {
        ///<summary>
        ///</summary>
        public const string ExploreVerb = "explore";

        ///<summary>
        ///</summary>
        public const string OpenVerb = "open";

        private readonly byte[][] _fqPidl;

        ///<summary>
        ///</summary>
        ///<param name="fqPidl"></param>
        ///<param name="text"></param>
        ///<param name="helpText"></param>
        ///<param name="verb"></param>
        ///<exception cref="ArgumentNullException"></exception>
        public ExploreMenuItem(byte[][] fqPidl, string text, string helpText, string verb)
            : base(null, false, false, true, helpText, false, false, text, verb)
        {
            if (fqPidl == null)
            {
                throw new ArgumentNullException("fqPidl");
            }

            this._fqPidl = fqPidl;
            Click += this.OnClick;
        }

        ///<summary>
        ///</summary>
        ///<param name="sender"></param>
        ///<param name="e"></param>
        ///<exception cref="Exception"></exception>
        public void OnClick(object sender, EventArgs e)
        {
            using (Malloc m = Shell32.GetMalloc())
            {
                var c = (ContextMenuEventArgs)e;

                var sei = new ShellExecuteInfo
                              {
                                  cbSize = (uint)Marshal.SizeOf(typeof (ShellExecuteInfo)),
                                  fMask = ShellExecuteOptions.IDList | ShellExecuteOptions.ClassName
                              };
                ItemIDList itemIdList = ItemIDList.Create(m, this._fqPidl);
                sei.lpIDList = itemIdList.Ptr;
                sei.lpClass = "folder";
                sei.hwnd = c.CommandInfo.hwnd;
                sei.nShow = c.CommandInfo.nShow;
                sei.lpVerb = this.Verb;

                var result = Shell32.ShellExecuteEx(ref sei);

                m.Free(itemIdList.Ptr);

                if (result)
                {
                    int lastError = Marshal.GetLastWin32Error();
                    throw new Exception("ShellExecuteEx failed; last error = " + lastError);
                }
            }
        }
    } ;
}
